﻿using ICSharpCode.SharpZipLib.Zip;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace GKQC.Common
{
    public class Tools
    {
        static readonly string E = "E";
        static readonly char Ec = 'E';
        static readonly string jia = "+";
        static readonly string jian = "-";
        static readonly char jianc = '-';
        static readonly char ling = '0';
        static readonly char dotc = '.';
        static readonly string x10 = "x10";

        /// <summary>
        /// 去掉最大最小值然后求平均
        /// </summary>
        /// <param name="values"></param>
        /// <param name="times">去掉多少次</param>
        public static decimal RemoveMaxMinThenAvg(List<decimal> values)
        {
            if (values == null) return 0;
            decimal value = values.Average();
            if (values == null || values.Count <= 3)
            {
                return value;
            }
            else
            {
                values.Remove(values.Max());
                values.Remove(values.Min());
                if (values.Count > 0) value = values.Average();
            }

            return value;
        }

        /// <summary>
        /// 获取小数位数
        /// </summary>
        /// <param name="decimalV">小数</param>
        /// <returns></returns>
        public static int GetNumberOfDecimalPlaces(double decimalV)
        {
            int result = 0;
            string[] temp = decimalV.ToString().Split(new char[] { dotc }
            , StringSplitOptions.RemoveEmptyEntries);
            if (temp.Length == 2 && temp[1].Length > 0 && !temp[1].ToUpper().Contains(E))
            {
                int index = temp[1].Length - 1;
                while (temp[1][index] == ling && index-- > 0) ;
                result = index + 1;
            }
            else
            {
                temp = decimalV.ToString().Split(new char[] { jianc }
                , StringSplitOptions.RemoveEmptyEntries);
                if (temp.Length == 2 && temp[1].Length > 0)
                {
                    result = int.Parse(temp[1]);
                }
                string s = temp[0].Substring(0, temp[0].Length - 1);
                temp = s.Split(dotc);
                if (temp.Length == 2 && temp[1].Length > 0)
                {
                    int index = temp[1].Length - 1;
                    while (temp[1][index] == ling && index-- > 0) ;
                    result = result + index + 1;
                }
            }
            return result;
        }

        /// <summary>
        /// 把数字转换为 x×10的N次方
        /// </summary>
        /// <param name="d"></param
        /// <param name="num">小數位數</param>
        /// <returns></returns>
        public static string To10NPower(double d, int num=10)
        {
            string s = d.ToString(E).ToUpper();////5.000000E+010
            string[] ss = s.Split(Ec);//E
            string s1 = Math.Round(double.Parse(ss[0]), num).ToString() + x10;//5x10
            string s2 = string.Empty;
            if (ss[1].Contains(jian))
                s2 = jian + ss[1].Replace(jian, string.Empty).TrimStart(ling);
            else if (ss[1].Contains(jia))
                s2 = ss[1].Replace(jia, string.Empty).TrimStart(ling); //10
            else
                s2 = ss[1].TrimStart(ling); //10

            return s1 + ToUpLabels(s2);
        }

        /// <summary>
        /// 返回上标
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static string ToUpLabels(string s)
        {
            if (string.IsNullOrWhiteSpace(s)) return string.Empty;

            string ss = string.Empty;
            StringBuilder sb = new StringBuilder();
            foreach(char c in s)
            {
                sb.Append(GetSuperChar(c.ToString()));
            }

            return sb.ToString();
        }

        /// <summary>
        /// 返回下标
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static string ToDownLabels(string s)
        {
            if (string.IsNullOrWhiteSpace(s)) return string.Empty;

            string ss = string.Empty;
            StringBuilder sb = new StringBuilder();
            foreach (char c in s)
            {
                sb.Append(GetSubChar(c.ToString()));
            }

            return sb.ToString();
        }

        /// <summary>
        /// 上标
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string GetSuperChar(string str)
        {
            switch (str)
            {
                case "0": return "\x2070";
                case "1": return "\x00B9";
                case "2": return "\x00B2";
                case "3": return "\x00B3";
                case "4": return "\x2074";
                case "5": return "\x2075";
                case "6": return "\x2076";
                case "7": return "\x2077";
                case "8": return "\x2078";
                case "9": return "\x2079";
                case "+": return "\x207A";
                case "-": return "\x207B";
                default: return string.Empty;
            }
            return str;
        }
        /// <summary>
        /// 下标
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string GetSubChar(string str)
        {
            switch (str)
            {
                case "0": return "\x2080";
                case "1": return "\x2081";
                case "2": return "\x2082";
                case "3": return "\x2083";
                case "4": return "\x2084";
                case "5": return "\x2085";
                case "6": return "\x2086";
                case "7": return "\x2087";
                case "8": return "\x2088";
                case "9": return "\x2089";
                case "+": return "\x208A";
                case "-": return "\x208B";
                default: return string.Empty;
            }
            return str;
        }

        /// <summary>
        /// 科學計數法字符串转换成数decimal值
        /// </summary>
        /// <param name="strNum"></param>
        /// <returns></returns>
        public static decimal Convert2Decimal(string strNum)
        {
            decimal result = 0m;
            try
            {
                if (string.IsNullOrEmpty(strNum))
                {
                    return 0m;
                }
                if (strNum.Contains("e") || strNum.Contains("E"))
                {
                    List<string> list = new List<string>();
                    if (strNum.Contains("e"))
                        list.AddRange(strNum.Split('e'));
                    else
                        list.AddRange(strNum.Split('E'));
                    if (list.Count != 2)
                    {
                        return 0m;
                    }
                    double num1 = 0;
                    if (!double.TryParse(list[0], out num1)) return 0m;
                    int num2 = 1;
                    if (!int.TryParse(list[1], out num2)) return 0m;
                    if (num2 > 28 || num2 < -28) //decimal上下限为10的±28次冪,超过这个值就不处理
                    {
                        return 0m;
                    }
                    result = Convert.ToDecimal(num1 * Math.Pow(10.0, num2));
                }
            }
            catch (System.Exception ex)
            {
                Logger.LogMessage(strNum);
                Logger.LogError(ex);
            }

            return result;
        }

        /// <summary>
        /// AQL數量計算
        /// </summary>
        /// <param name="qty">批量</param>
        /// <param name="qty0">0.01抽樣數</param>
        /// <param name="qty004">0.04抽樣數</param>
        /// <param name="qty01">0.1抽樣數</param>
        /// <param name="accept0">0.01允收數</param>
        /// <param name="accept004">0.04允收數</param>
        /// <param name="accept01">0.1允收數</param>
        /// <param name="reject0">0.01拒收數</param>
        /// <param name="reject004">0.04拒收數</param>
        /// <param name="reject01">0.1拒收數</param>
        /// <param name="custoemrCode">客戶代號</param>
        public static void GetAQL(double qty, out double qty0, out double qty004, out double qty01
            , out double accept0, out double accept004, out double accept01
            , out double reject0, out double reject004, out double reject01
            , string custoemrCode
            )
        {
            qty0 = qty004 = qty01 = 0;
            accept0 = accept004 = accept01 = reject0 = reject004 = reject01 = 0;

            GetAQL(qty, out qty0, out qty004, out qty01
            , out accept0, out accept004, out accept01
            , out reject0, out reject004, out reject0
            );

            if (custoemrCode == "0728" || custoemrCode == "1053") //冠德0728  1053北海建源
            {
                Tools.GetAql_0728(qty, out qty0, out qty004
                    , out accept0, out accept004
                    , out reject0, out reject004
                    );

                qty01 = qty004;
                accept01 = accept004;
                reject01 = reject004;
            }
            else if (custoemrCode == "0036") //美隆0036 
            {
                Tools.GetAql_0036(qty, out qty0, out qty004
                    , out accept0, out accept004
                    , out reject0, out reject004
                    );

                qty01 = qty004;
                accept01 = accept004;
                reject01 = reject004;
            }
            else if (custoemrCode == "0916") //欧陆通0916
            {
                Tools.GetAql_0916(qty, out qty0);
                qty004 = qty0;
                qty01 = qty0;
            }
            else if (custoemrCode == "0372") //富华0372
            {
                Tools.GetAql_0372(qty, out qty0);
                qty004 = qty0;
                qty01 = qty0;
            }
        }

        /// <summary>
        /// AQL數量計算
        /// </summary>
        /// <param name="qty">批量</param>
        /// <param name="qty0">0.01抽樣數</param>
        /// <param name="qty004">0.04抽樣數</param>
        /// <param name="qty01">0.1抽樣數</param>
        /// <param name="accept0">0.01允收數</param>
        /// <param name="accept004">0.04允收數</param>
        /// <param name="accept01">0.1允收數</param>
        /// <param name="reject0">0.01拒收數</param>
        /// <param name="reject004">0.04拒收數</param>
        /// <param name="reject01">0.1拒收數</param>
        public static void GetAQL(double qty, out double qty0, out double qty004, out double qty01
            , out double accept0, out double accept004, out double accept01
            , out double reject0, out double reject004, out double reject01
            )
        {
            qty0 = qty004 = qty01 = 0;
            accept0 = accept004 = accept01 = reject0 = reject004 = reject01=0;

            //0
            if (qty < 1250) qty0 = qty;
            else qty0 = 1250;
            //0.04
            if (qty <= 315) qty004 = qty;
            else if (qty >= 315 && qty < 150001) qty004 = 315;
            else qty004 = 1250;
            //0.1
            if (qty < 125) qty01 = qty;
            else if (qty >= 125 && qty < 10001) qty01 = 125;
            else if (qty >= 10001 && qty < 150001) qty01 = 500;
            else if (qty >= 150001 && qty < 500001) qty01 = 800;
            else qty01 = 1250;

            //0
            accept0 = 0; reject0 = 1;
            //0.04
            if (qty <= 150000)
            {
                accept004 = 0;
                reject004 = 1;
            }
            else
            {
                accept004 = 1;
                reject004 = 2;
            }
            //0.1
            if (qty <= 10000)
            {
                accept01 = 0;
                reject01 = 1;
            }
            else if(qty > 10000 && qty <=150000)
            {
                accept01 = 1;
                reject01 = 2;
            }
            else if (qty > 150000 && qty <= 500000)
            {
                accept01 = 2;
                reject01 = 3;
            }
            else
            {
                accept01 = 2;
                reject01 = 3;
            }
        }

        /// <summary>
        /// 冠德抽样计划
        /// </summary>
        /// <param name="qty">批量</param>
        /// <param name="qty015">MA0.15抽样数</param>
        /// <param name="qty025">MI0.25抽样数</param>
        /// <param name="accept015">MA0.15允收数</param>
        /// <param name="accept025">MI0.25允收数</param>
        /// <param name="reject015">MA0.15拒收数</param>
        /// <param name="reject025">MI0.25拒收数</param>
        public static void GetAql_0728(double qty, out double qty015, out double qty025
            , out double accept015, out double accept025
            , out double reject015, out double reject025)
        {
            qty015 = qty025 = 0;
            accept015 = accept025 = reject015 = reject025 = 0;

            #region MA015
            if (qty <= 80)
            {
                qty015 = qty;
                accept015 = 0;
                reject015 = 1;
            }
            else if (qty > 80 && qty <= 3200)
            {
                qty015 = 80;
                accept015 = 0;
                reject015 = 1;
            }
            else if(qty > 3200 && qty <= 35000)
            {
                qty015 = 315;
                accept015 = 1;
                reject015 = 2;
            }
            else if (qty > 35000 && qty <= 150000)
            {
                qty015 = 500;
                accept015 = 2;
                reject015 = 3;
            }
            else if (qty > 150000 && qty <= 500000)
            {
                qty015 = 800;
                accept015 = 3;
                reject015 = 4;
            }
            else if (qty > 500000)
            {
                qty015 = 1250;
                accept015 = 5;
                reject015 = 6;
            }
            #endregion MA015

            #region MI025
            if (qty <= 50)
            {
                qty025 = qty;
                accept025 = 0;
                reject025 = 1;
            }
            else if (qty > 50 && qty <= 1200)
            {
                qty025 = 50;
                accept025 = 0;
                reject025 = 1;
            }
            else if (qty > 1200 && qty <= 10000)
            {
                qty025 = 200;
                accept025 = 1;
                reject025 = 2;
            }
            else if (qty > 10000 && qty <= 35000)
            {
                qty025 = 315;
                accept025 = 2;
                reject025 = 3;
            }
            else if (qty > 35000 && qty <= 150000)
            {
                qty025 = 500;
                accept025 = 3;
                reject025 = 4;
            }
            else if (qty > 150000 && qty <= 500000)
            {
                qty025 = 800;
                accept025 = 5;
                reject025 = 6;
            }
            else if (qty > 500000)
            {
                qty025 = 1250;
                accept025 = 7;
                reject025 = 8;
            }
            #endregion MI025
        }

        /// <summary>
        /// 美隆抽样计划
        /// </summary>
        /// <param name="qty">批量</param>
        /// <param name="qty025">MA0.25抽样数</param>
        /// <param name="qty015">MI1.00抽样数</param>
        /// <param name="accept015">MA0.25允收数</param>
        /// <param name="accept025">MI1.00允收数</param>
        /// <param name="reject015">MA0.25拒收数</param>
        /// <param name="reject025">MI1.00拒收数</param>
        public static void GetAql_0036(double qty, out double qty025, out double qty015
            , out double accept015, out double accept025
            , out double reject015, out double reject025)
        {
            qty025 = qty015 = 0;
            accept015 = accept025 = reject015 = reject025 = 0;

            #region MA025
            if (qty <= 50)
            {
                qty025 = qty;
                accept025 = 0;
                reject025 = 1;
            }
            else if (qty > 50 && qty <= 500)
            {
                qty025 = 50;
                accept025 = 0;
                reject025 = 1;
            }
            else if (qty > 500 && qty <= 1200)
            {
                qty025 = 80;
                accept025 = 0;
                reject025 =1;
            }
            else if (qty > 1200 && qty <= 10000)
            {
                qty025 = 200;
                accept025 = 1;
                reject025 = 2;
            }
            else if (qty > 10000 && qty <= 35000)
            {
                qty025 = 315;
                accept025 = 2;
                reject025 = 3;
            }
            else if (qty > 35000 && qty <= 150000)
            {
                qty025 = 500;
                accept025 = 3;
                reject025 = 4;
            }
            else if (qty > 150000 && qty <= 500000)
            {
                qty025 = 800;
                accept025 = 5;
                reject025 = 6;
            }
            else if (qty > 500000)
            {
                qty025 = 1250;
                accept025 = 7;
                reject025 = 8;
            }
            #endregion MA025

            #region MI1.00
            if (qty <= 50)
            {
                qty015 = qty;
                accept015 = 0;
                reject015 = 1;
            }
            else if (qty > 50 && qty <= 150)
            {
                qty015 = 50;
                accept015 = 0;
                reject015 = 1;
            }
            else if (qty > 150 && qty <= 500)
            {
                qty015 = 50;
                accept015 = 1;
                reject015 = 2;
            }
            else if (qty > 500 && qty <= 1200)
            {
                qty015 = 80;
                accept015 = 2;
                reject015 = 3;
            }
            else if (qty > 1200 && qty <= 3200)
            {
                qty015 = 200;
                accept015 = 3;
                reject015 = 4;
            }
            else if (qty > 3200 && qty <= 10000)
            {
                qty015 = 200;
                accept015 = 5;
                reject015 = 6;
            }
            else if (qty > 10000 && qty <= 35000)
            {
                qty015 = 315;
                accept015 = 7;
                reject015 = 8;
            }
            else if (qty > 35000 && qty <= 150000)
            {
                qty015 = 500;
                accept015 = 10;
                reject015 = 11;
            }
            else if (qty > 150000 && qty <= 500000)
            {
                qty015 = 800;
                accept015 = 14;
                reject015 = 15;
            }
            else if (qty > 500000)
            {
                qty015 = 1250;
                accept015 = 21;
                reject015 = 22;
            }
            #endregion MI1.00
        }

        /// <summary>
        /// 欧陆通抽样计划
        /// </summary>
        /// <param name="qty">批量</param>
        /// <param name="qty0">抽样数</param>
        /// <param name="accept0">允收数</param>
        /// <param name="reject0">拒收数</param>
        public static void GetAql_0916(double qty, out double qty0)
        {
            qty0 = 0;

            #region MA025
            if (qty <= 80)
            {
                qty0 = qty;
            }
            else if (qty > 80 && qty <= 960)
            {
                qty0 = 80;
            }
            else if (qty > 960 && qty <= 1632)
            {
                qty0 = 96;
            }
            else if (qty > 1632 && qty <= 3072)
            {
                qty0 = 128;
            }
            else if (qty > 3072 && qty <= 5440)
            {
                qty0 = 160;
            }
            else if (qty > 5440)
            {
                qty0 = 192;
            }
            #endregion MA025
        }

        /// <summary>
        /// 富華抽样计划0372
        /// </summary>
        /// <param name="qty">批量</param>
        /// <param name="qty0">抽样数</param>
        public static void GetAql_0372(double qty, out double qty0)
        {
            qty0 = 0;

            #region 
            if (qty <= 1)
            {
                qty0 = 1;
            }
            else if (qty > 1 && qty <= 8)
            {
                qty0 = 2;
            }
            else if (qty > 8 && qty <= 15)
            {
                qty0 = 3;
            }
            else if (qty > 15 && qty <= 25)
            {
                qty0 = 5;
            }
            else if (qty > 25 && qty <= 50)
            {
                qty0 = 8;
            }
            else if (qty > 50 && qty <= 90)
            {
                qty0 = 13;
            }
            else if (qty > 90 && qty <= 150)
            {
                qty0 = 20;
            }
            else if (qty > 150 && qty <= 280)
            {
                qty0 = 32;
            }
            else if (qty > 280 && qty <= 500)
            {
                qty0 = 50;
            }
            else if (qty > 500 && qty <= 1200)
            {
                qty0 = 80;
            }
            else if (qty > 1200 && qty <= 3200)
            {
                qty0 = 125;
            }
            else if (qty > 3200 && qty <= 10000)
            {
                qty0 = 200;
            }
            else if (qty > 10000 && qty <= 35000)
            {
                qty0 = 315;
            }
            else if (qty > 35000 && qty <= 150000)
            {
                qty0 = 500;
            }
            else if (qty > 150000 && qty <= 500000)
            {
                qty0 = 800;
            }
            else if (qty > 500000)
            {
                qty0 = 800;
            }
            #endregion 
        }

        public static string GetEnumDescription<TEnum>(string name)
        {

            Type enumType = typeof(TEnum);

            if (!enumType.IsEnum)
            {
                return string.Empty;
            }

            if (name == null)
                return string.Empty;

            object[] objs = enumType.GetField(name).GetCustomAttributes(typeof(DescriptionAttribute), false);

            if (objs == null || objs.Length == 0)
            {
                return string.Empty;
            }
            else
            {
                DescriptionAttribute attr = objs[0] as DescriptionAttribute;

                return attr.Description;
            }
        }

        /// <summary>
        /// 获取字符串前面的数字,负一表示字符串前面不是数字
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static int GetFrontNumberOfString(string s)
        {
            int i = -1;
            StringBuilder sb = new StringBuilder();
            foreach(char c in s)
            {
                if (Char.IsDigit(c)) sb.Append(c.ToString());
                else break;
            }
            if (sb.Length > 0)
                int.TryParse(sb.ToString(), out i);
            return i;
        }

        public static string Trim(string s)
        {
            if (string.IsNullOrWhiteSpace(s)) return string.Empty;
            return s.Replace("\n", "").Replace(" ","").Replace("\t","").Replace("\r","");
        }

        public static string ReadTextFileFirstRow(string fileName)
        {
            string s = string.Empty;
            try
            {
                using (StreamReader sr = new StreamReader(fileName, Encoding.Default))
                {
                    String line;
                    while ((line = sr.ReadLine()) != null)
                    {
                        s = line.ToString();
                        break;
                    }
                    sr.Close();
                    sr.Dispose();
                }
            }
            catch (IOException ex)
            {
                Logger.LogError(ex);
            }

            return s;
        }

        /// <summary>
        /// 功能：解压zip格式的文件。
        /// </summary>
        /// <param name="zipFilePath">压缩文件路径</param>
        /// <param name="unZipDir">解压文件存放路径,为空时默认与压缩文件同一级目录下，跟压缩文件同名的文件夹</param>
        /// <param name="err">出错信息</param>
        /// <returns>解压是否成功</returns>
        public static bool UnZipFile(string zipFilePath, string unZipDir, out string err)
        {
            err = "";
            if (zipFilePath == string.Empty)
            {
                err = "压缩文件不能为空！";
                return false;
            }
            if (!File.Exists(zipFilePath))
            {
                err = "压缩文件不存在！";
                return false;
            }
            //解压文件夹为空时默认与压缩文件同一级目录下，跟压缩文件同名的文件夹
            if (unZipDir == string.Empty)
                unZipDir = zipFilePath.Replace(Path.GetFileName(zipFilePath), Path.GetFileNameWithoutExtension(zipFilePath));
            if (!unZipDir.EndsWith("\\"))
                unZipDir += "\\";
            if (!Directory.Exists(unZipDir))
                Directory.CreateDirectory(unZipDir);

            try
            {
                using (ZipInputStream s = new ZipInputStream(File.OpenRead(zipFilePath)))
                {
                    ZipEntry theEntry;
                    while ((theEntry = s.GetNextEntry()) != null)
                    {
                        string directoryName = Path.GetDirectoryName(theEntry.Name);
                        string fileName = Path.GetFileName(theEntry.Name);
                        if (directoryName.Length > 0)
                        {
                            Directory.CreateDirectory(unZipDir + directoryName);
                        }
                        if (!directoryName.EndsWith("\\"))
                            directoryName += "\\";
                        if (fileName != String.Empty)
                        {
                            using (FileStream streamWriter = File.Create(unZipDir + theEntry.Name))
                            {

                                int size = 2048;
                                byte[] data = new byte[2048];
                                while (true)
                                {
                                    size = s.Read(data, 0, data.Length);
                                    if (size > 0)
                                    {
                                        streamWriter.Write(data, 0, size);
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                            }
                        }
                    }//while
                }
            }
            catch (Exception ex)
            {
                err = ex.Message;
                return false;
            }
            return true;
        }//解压结束

        /// <summary>
        /// 获取小数位位数
        /// </summary>
        /// <param name="d"></param>
        /// <returns></returns>
        public static int GetDoubleNum(double d)
        {
            int num = 0;

            string numS = d.ToString();
            if(numS.Contains("."))
            {
                num = numS.Length - numS.LastIndexOf(".")-1;
            }

            return num;
        }

        /// <summary>
        /// 判断输入的字符串是否只包含数字和英文字母
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static bool IsNumAndEnCh(string input)
        {
            string pattern = @"^[A-Za-z0-9]+$";
            Regex regex = new Regex(pattern);
            return regex.IsMatch(input);
        }

        /// <summary>
        /// 文件名是否合法
        /// </summary>
        /// <param name="invalidCHars">非法字符</param>
        /// <param name="value">要比较的字符串</param>
        /// <returns></returns>
        public static bool FileNameIsValid(string filename)
        {
            bool flag = true;
            if (string.IsNullOrWhiteSpace(filename)) return false;

            flag = Regex.IsMatch(filename, @"(?!((^(con)$)|^(con)\\..*|(^(prn)$)|^(prn)\\..*|(^(aux)$)|^(aux)\\..*|(^(nul)$)|^(nul)\\..*|(^(com)[1-9]$)|^(com)[1-9]\\..*|(^(lpt)[1-9]$)|^(lpt)[1-9]\\..*)|^\\s+|.*\\s$)(^[^\\\\\\/\\:\\<\\>\\*\\?\\\\\\""\\\\|]{1,255}$)");

            return flag;
        }
    }
}
